
/**
*
* Base object for describing the animation of a State.
*
* @author	Jovan Alleyne
* @version	1.0a
* @since	Flash 9
*
*/

package org.hive.sequence
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.utils.Dictionary;
	import org.hive.state.State;
	import org.hive.events.SequenceEvent;

	public class Sequence extends EventDispatcher
	{
		/**
		* Flag set to determine if the sequence has
		* started animating.
		*
		* @private
		*/
		protected var __active:Boolean = false;

		/**
		* Unique name for this sequence.
		*
		* @private
		*/
		protected var __name:String;

		/**
		* Type of event that will trigger the complete event
		* to be fired from a sequence.
		*
		* @private
		* @see __completeEventSource;
		*/
		protected var __completeEventName:String;

		/**
		* Object that will trigger a complete event type.
		*
		* @private
		* @see __completeEventName
		*/
		protected var __completeEventSource:*;
		
		/**
		* Collection of actions that have been pushed onto
		* this sequence to describe the animations.
		*
		* @private
		* @see __REPOSITORY_PARAM
		*/
		protected var __REPOSITORY:Array = new Array();
		private var __REPOSITORY_PARAM:Dictionary = new Dictionary( false );
		
		/**
		*
		* @param	name
		* @param	actions
		*/
		public function Sequence( name:String, actions:Array=null )
		{
			super();
			__name = name;
			
			if( actions )
				__REPOSITORY = actions;
		}
		
		/**
		*
		* @return
		*/
		public function get name( ):String
		{
			return __name;
		}
		
		/**
		*
		* @param	action
		* @param	object
		* @param	...args
		* @return
		*/
		public function pushBefore( action:*, object:*, ...args ):Number
		{
			if( args.length )
				__REPOSITORY_PARAM[ action ] = args;
			
			return pushAt( action, __REPOSITORY.indexOf( object )-1 );
		}

		/**
		*
		* @param	action
		* @param	object
		* @param	...args
		* @return
		*/
		public function pushAfter( action:*, object:*, ...args ):Number
		{
			if( args.length )
				__REPOSITORY_PARAM[ action ] = args;
			
			return pushAt( action, __REPOSITORY.indexOf( object )+1 );
		}
		
		/**
		*
		* @param	action
		* @param	position
		* @param	...args
		* @return
		*/
		public function pushAt( action:*, position:Number, ...args ):Number
		{
			if( args.length )
				__REPOSITORY_PARAM[ action ] = args;
			
			var slice1:Array = __REPOSITORY.slice( 0, position );
			var slice2:Array = __REPOSITORY.slice( position );
			
			slice1.push( action );
			__REPOSITORY = slice1.concat( slice2 );
			
			return slice1.length - 1;
		}
		
		/**
		*
		* @param	action
		* @param	...args
		* @return
		*/
		public function push( action:*, ...args ):Number
		{
			if( args.length )
				__REPOSITORY_PARAM[ action ] = args;
			
			return __REPOSITORY.push( action );
		}
		
		/**
		*
		* @param	num
		*/
		public function index( num:Number ):*
		{
			return __REPOSITORY[ num ];
		}
		
		public function slice( startIndex:Number=0, endIndex:Number=16777215 ):*
		{
			/*var seq:ActionSequence 		= new ActionSequence( __name, __REPOSITORY.slice( startIndex, endIndex ) );
			//var seq:ActionSequence 		= new ActionSequence( __name, __REPOSITORY.slice( startIndex, endIndex ) );
			
			seq.completeTriggerName 	= __completeEventName;
			seq.completeTriggerSource 	= __completeEventSource;

			if( __active ) {
				if( seq.length ) kill( );
			}*/

			return null;
		}
		
		public function reset( ):void
		{
			__REPOSITORY.splice(0, __REPOSITORY.length);
			// remove all keys from the dictionary
			for (var key:Object in __REPOSITORY_PARAM) {
				delete __REPOSITORY_PARAM[key]; //removes the key
			}
		}
		
		
		/**
		* @private
		*/
		protected var __complete:Boolean = false;


		public function set complete( value:Boolean ):void
		{
		    __complete = value;
		}

		public function get complete( ):Boolean
		{
		    return __complete;
		}

		/**
		*
		* @return
		*/
		public function kill( ):void
		{
		    if( __completeEventSource ){
			__completeEventSource.removeEventListener( __completeEventName, handleSequenceEnd );
		    }
		}
		
		/**
		*
		* @return
		*/
		public function activate( ):void
		{
			if( __completeEventSource && __completeEventName && !__active ) {
				__active = true;
				__completeEventSource.addEventListener( __completeEventName, handleSequenceEnd, false, 0, true );
			}
		}
		
		/**
		*
		* @param	e
		* @return
		*/
		internal function handleSequenceEnd( e:Event ):void
		{
			__completeEventSource.removeEventListener( __completeEventName, handleSequenceEnd );
		}

		/**
		*
		* @param	action
		* @return
		*/
		public function getParams( action:* ):Array
		{
			return __REPOSITORY_PARAM[ action ];
		}

		//______________________________________________________________________________ GETTERS and SETTERS
		
		
		public function get length( ):Number
		{
			return __REPOSITORY.length;
		}
		
		public function get active( ):Boolean
		{
			return __active;
		}
		
		public function set completeTriggerName( eventName:String ):void
		{
			__completeEventName = eventName;
		}
		
		public function get completeTriggerName( ):String
		{
			return __completeEventName;
		}
		
		public function set completeTriggerSource( source:* ):void
		{
			__completeEventSource = source;
		}
		
		public function get completeTriggerSource( ):*
		{
			return __completeEventSource;
		}
				
		/**
		* @private
		*/
		public override function toString():String
		{
			var returnString:String = "[Sequence \n \t" + __name ;
			returnString += "\t\t" + __REPOSITORY.toString( ) + " ]";
			
			return returnString;
		}
	}
	
}
